<?php
/**
 * Created by PhpStorm.
 * User: DD
 * Date: 2016/6/13
 * Time: 20:43
 */

namespace app\common\util\weixin;

/**
 * Class Dispatcher
 * 微信消息分发器
 *
 * @package app\common\util\weixin
 */
class Dispatcher
{
    /**
     * @var Request
     */
    private $_request;
    private $_events;

    public function __construct()
    {
        $this->_events = [];
        $this->_request = new Request();
    }

    public function getRequest()
    {
        return $this->_request;
    }

    public function addEventListener($event, $handler)
    {
        if (!isset($this->_events[$event])) {
            $this->_events[$event] = [];
        }
        $this->_events[$event][] = $handler;
    }

    public function removeEventListener($event, $handler = null)
    {
        if (isset($this->_events[$event])) {
            if (!$handler) {
                unset($this->_events[$event]);
            } else {
                foreach ($this->_events[$event] as $k => $e) {
                    if ($e == $handler) {
                        unset($this->_events[$event][$k]);
                    }
                }
            }
        }
    }

    public function clearEventListeners()
    {
        unset($this->_events);
    }

    private function emitEvent($event)
    {
        if (isset($this->_events[$event])) {
            foreach ($this->_events[$event] as $e) {
                $rt = call_user_func($e, $this->_request);
                if ($rt === false) {
                    break;
                }
            }
        }
    }

    /**
     *  msgtype:
     *      event:
     *          subscribe:关注,
     *          scan:扫描二维码,
     *          location:地理位置,
     *          click:自定义菜单 - 点击菜单拉取消息时的事件推送，
     *          view:自定义菜单 - 点击菜单跳转链接时的事件推送
     *          scancode_push:自定义菜单 - 扫码推事件的事件推送
     *          scancode_waitmsg:自定义菜单 - 扫码推事件且弹出“消息接收中”提示框的事件推送
     *          templatesendjobfinish:模板消息完成后推送的结果
     */
    public function dispatch()
    {
        $request = $this->_request;
        if ($request->msgtype == 'event') {
            $this->emitEvent(strtolower($request->msgtype . '.' . $request->event));
        } else {
            $this->emitEvent(strtolower($request->msgtype));
        }
    }

    public static function instance()
    {
        return new self();
    }
}